package orm

import (
	"reflect"
	"errors"
)

//model->table
type ModelInfo struct {
	TableName string
	RefVal reflect.Value
	Columns []Column

}

type Column struct {
	ColumnName string
	ColumnType string
	Constraints string
}

func GetModelInfo(model interface{})(*ModelInfo,error){
	table,err := getModelName(model)
	if err!=nil{
		return nil,err
	}

	rows ,err := getModelRows(model)
	if err!=nil{
		return nil,err
	}

	modelInfo := &ModelInfo{}
	modelInfo.TableName = table
	modelInfo.Columns = rows
	modelInfo.RefVal = reflect.ValueOf(model)

	return modelInfo,nil
}

func getModelName(arg interface{})(string,error){
	typ := reflect.TypeOf(arg)
	if typ.Kind() != reflect.Ptr{
		return typ.Name(),nil
	}

	if typ.Elem().Kind() == reflect.Slice{
	}
	return typ.Elem().Name(),nil
}

func getModelRows(arg interface{})([]Column,error){
	if arg == nil{
		return nil,errors.New("model is nil")
	}

	var Columns []Column

	typ := reflect.TypeOf(arg)
	var typElem reflect.Type
	if typ.Kind() != reflect.Ptr{
		typElem = typ
		return nil,errors.New("must input ptr")
	}else{
		typElem = typ.Elem()
	}

	for i:=0;i<typElem.NumField();i++{
		var column Column
		column.ColumnName = typElem.Field(i).Name

		if DbType := typElem.Field(i).Tag.Get("type");DbType!=""{
			column.ColumnType = DbType
		}else{
			DbType ,err:= matchingType(Orm.dataType,typElem.Field(i).Type.Name())
			if err!=nil{
				return nil,err
			}
			column.ColumnType = DbType
		}

		if DbConstraint := typElem.Field(i).Tag.Get("constraint");DbConstraint!=""{
			column.Constraints = DbConstraint
		}

		Columns = append(Columns,column)
	}

	return Columns,nil
}

//match row type with db type
func matchingType(types *map[string]string,typeName string)(string,error){
	if v,ok := (*types)[typeName];ok{
		return v,nil
	}

	return "",errors.New("match data type fail,no this type in db "+typeName)
}

